package model;
import java.util.List;

import model.player.*;
import controller.Controller;
import model.playable.Playable;
import view.View;
import model.item.ItemPopulator;
import model.map.GameMap;
import model.map.MapMaker;
import model.mapping.ItemMapping;
import model.mapping.PlayableMapping;
import model.player.Player;
import model.resource.MapResourcePopulator;
import model.visibility.PlayerView;

/**
 * Initiates the subsystems of the model; and possibly does more.
 *
 * @author 
 */
public class Model {
	MapMaker mapMaker = MapMaker.mapMaker;
	
	private Controller controller;
    private View view;
	private Player human, ai;
	private List<String> walkableTerrains, vehicleTerrains;
	
	public Model(){
		GameMap gameMap = mapMaker.getNewMap();
		walkableTerrains = mapMaker.getTerrainsWalkableByAll();
		vehicleTerrains = mapMaker.getTerrainsWalkableByVehicles();
		PlayableMapping.getPlayableMapping().setMap(gameMap);
		MapResourcePopulator.getResourcePopulator().populate(gameMap);
		ItemPopulator.getItemPopulator().populate(gameMap);
		ItemMapping.getItemMapping().setPlayableMapping(PlayableMapping.getPlayableMapping());
		human = new Player(gameMap, gameMap.getNextStartingLocation(), walkableTerrains, vehicleTerrains);
		ai = new Player(gameMap, gameMap.getNextStartingLocation(), walkableTerrains, vehicleTerrains);
		
	}
	public PlayerView getPlayerView()
	{	
		return human.getPlayerView();
	}
	
	public ControllablePlayer getControllablePlayer()
	{
		return human.getControllablePlayer();
	}
    /**
     * Cycles directly to the nth element in the list of
     * this type of subtype
     *
     * @param number
     * @return
     */
    public Playable getInstance(int number){
        return getControllablePlayer().getCurType().getCurSubType().getPlayableID(number);
    }
    /**
     * Gets the next instance of this type and sub type of playable
     *
     * @return
     */
    public Playable getNextInstance(){
        Playable a = getControllablePlayer().getCurType().getCurSubType().getCurPlayable();
        if(a != null) System.out.println(a);
        return a;
    }
    /**
     * Gets the previous instance of this type and sub type of playable
     *
     * @return
     */
    public Playable getPrevInstance(){
        Playable a = getControllablePlayer().getCurType().getCurSubType().getPrevPlayable();
        if(a != null) System.out.println(a);
        return a;        
    }
    /**
     * Gets the next subtype of this type. This should automatically 
     * choose an instance to pass back to the callinf function.
     * 
     * @return
     */
    public Playable getNextSubtype(){
    	CyclableManager a = null;
    	while(a == null){
    		a = getControllablePlayer().getCurType().getNextSubType();
    	}
    	System.out.println("\t\t\tFOUND ONE " + a.getType());
    	if(a.getCurPlayable() != null){System.out.println(a.getCurPlayable());}
    	return a.getCurPlayable();
        //return getControllablePlayer().getCurType().getNextSubType().getCurPlayable();
    }
    /**
     * Gets the previous subtype of this type. This should automatically
     * choose an instance to pass back to the callinf function.
     *
     * @return
     */
    public Playable getPrevSubtype(){
    	CyclableManager a = null;
    	while(a == null){
    		a = getControllablePlayer().getCurType().getPrevSubType();
    	}
    	System.out.println("\t\t\tFOUND ONE " + a.getType());
    	if(a.getCurPlayable() != null){System.out.println(a.getCurPlayable());}
    	return a.getCurPlayable();
        //return getControllablePlayer().getCurType().getPrevSubType().getCurPlayable();
    }
    /**
     * Selects the next type. This should auto-select the subtype and
     * instance to pass back to the calling function.
     *
     * @return
     */
    public Playable getNextType(){
    	CyclableManager a = null;
    	while(a == null){
    		a = getControllablePlayer().getNextType().getCurSubType();
    	}
    	System.out.println("\t\t\tFOUND ONE " + a.getType());
    	if(a.getCurPlayable() != null){System.out.println(a.getCurPlayable());}
    	return a.getCurPlayable();
        //return getControllablePlayer().getNextType().getCurSubType().getCurPlayable();
    }
    /**
     * Similar as above
     * 
     * @return
     */
    public Playable getPrevType(){
    	CyclableManager a = null;
    	while(a == null){
    		a = getControllablePlayer().getPrevType().getCurSubType();
    	}
    	System.out.println("\t\t\tFOUND ONE " + a.getType());
    	if(a.getCurPlayable() != null){System.out.println(a.getCurPlayable());}
    	return a.getCurPlayable();
        //return getControllablePlayer().getPrevType().getCurSubType().getCurPlayable();
    }
    /**
     * 
     * @param controller
     */
    public void setController(Controller controller){
        this.controller = controller;
    }
    public Playable getInitialPlayable()
    {
        Playable p = getControllablePlayer().getCurType().getCurSubType().getCurPlayable();
        return p;
    }
    /**
     *
     * @param view
     */
    public void setView(View view){
        this.view = view;
    }
    /**
     * Ticks the model.
     */
    public void tick()
    {
    	human.update();
    	ai.update();
    }
}
